<?php
App::import('Vendor', 'linkbot');
App::import('Vendor', 'email_message');
App::import('Vendor', 'image');

class Cron extends AppModel{
	var $name = 'Cron';
	var $useTable          = 'markers';
	var $regionsTable      = 'regions';
	var $regionsCoordTable = 'regions_coord';

	var $destructionTable  = 'destruction';
	var $userPropsTable    = 'user_properties';
	var $usersInfoTable    = 'users_information';
	var $usersTable        = 'users';
	var $newsTable         = 'news';
	var $chatTable         = "chat";
	var $gameTable         = 'game_info';
	var $gameLocatonsTable = 'game_locations';
	var $gameTimeTable     = 'game_times'; 
	var $markerTable       = 'markers'; 
	var $markerNecessTable = 'markers_necessities'; 
	var $reasonableCond    = 80;
	//____________________________________________________
	var $necessityUnits        = 10;
	var $update_price_constant = 0.1; //constant for update price
	var $revenue_constant      = 0.5; //revenue value constant
	var $building_constant     = 10;
	var $maxSwarmPop           = 20000;
	var $minSwarmPop           = 10;
	var $PercentageRndMove     = 30; // in % the amount to move random from 1 region to another
	var $revenueConstant       = 7;

	//swarm constants_______________________________________________________
	//var $minimum_epsilon = 0.2;
	var $minimum_epsilon = 0;
	var $minimum_pop     = 10;
	var $swarm_cols      = 100;
	var $swarm_rows      = 100;
	var $swarm_cell_cols = 10;
	var $swarm_cell_rows = 10;
	//TODO: is adding or taking away 100 population to/from a cell not too much?
	//I made it to be a random number between 1 and 100 for now
	var $bornPopSwarm    = 10;
	var $avg_pop_at_init = 70;
	var $birth_rate      = 0.05;
	
	//create the entries in the table regions if they do not exist yet
	function initializeRegions($game_id){
		$result = $this->query("SELECT rc.`region_coord_id`
				FROM `{$this->regionsCoordTable}` as rc,
				 	`{$this->gameTable}` as g 
				WHERE g.`game_id` = {$game_id} 
				 	AND g.`game_location_id` = rc.`game_location_id`");
		foreach($result as $res){
			$this->query("INSERT INTO `{$this->regionsTable}`(`region_coord_id`,`game_id`) 
		 			VALUES({$res['rc']['region_coord_id']}, {$game_id})");
		}
	}
	
	function getGameIds(){
		$result = $this->query("SELECT DISTINCT `game_id`
				FROM `{$this->gameTable}`");
		$games = array();
		foreach($result as $res){
			$games[] = $res[$this->gameTable]['game_id']; 
		}
		return $games;
	}
	
	function cleanChat() {
		//remove all except for the last 50 for each game
		$games = $this->getGameIds();
		foreach($games as $game){
			$query = "SELECT c.`chat_id` 
					  FROM `{$this->chatTable}` as c,
					  	`{$this->gameTable}` as g 
					  WHERE c.`user_id` = g.`user_id` 
					  	AND g.`game_id` = {$game['game_id']}	
					  ORDER BY c.`chat_id` DESC
					  LIMIT 0,50";
			$result = $this->query($query);
			$chat_ids = "";
			foreach($result as $res){
				$chat_ids.=$res['c']['chat_id'].",";
			}
			if(strlen($chat_ids)>0){
				$chat_ids = substr($chat_ids,0,-1);
				$this->query("DELETE FROM `{$this->chatTable}` 
								WHERE `chat_id` NOT IN ({$chat_ids})");
			}	
		}
	}
	
	function getMarkers($game_id,$user_id="",$marker_id=""){
		$query = "SELECT m.*, u.`user_id`, u.`first_name`, u.`last_name`, p.`img_url`,
						 p.`property_id` ,p.`price_buy`, p.`forsale`, r.`region_worth`,
						 p.`property_name`, r.`region_id`
				FROM `{$this->useTable}` as `m`, `{$this->userPropsTable}` as `p`, 
						{$this->usersInfoTable} as `u`, {$this->regionsTable} as `r`,
						`{$this->gameTable}` as g
				WHERE m.`marker_id`=p.`marker_id` AND p.`user_id`= u.`user_id` 
					AND r.`region_id`=m.`region_id` 
					AND r.`game_id`=g.`game_id`  
					AND g.`user_id` = u.`user_id`
					AND g.`game_id` = {$game_id} 
					AND m.`valid`=1 ".
					(!empty($marker_id)?" AND m.`marker_id`={$marker_id} ":"").
					(!empty($user_id)?" AND u.`user_id`={$user_id} ":"");
		$result   = $this->query($query);
		$property = array();
		if(count($result)>0){
			foreach($result as $res){
				$property[] = array_merge($res["m"],$res["u"],$res["p"],$res["r"]);	
			}
		}
		if(!empty($marker_id)&&!empty($user_id)&&count($property)>0){
			return $property[0];
		}
		return $property;				
	}
	
	function cleanNewsTable() {
		$query = "SELECT n.`marker_id`, d.`destruction_impact` 
			FROM `{$this->newsTable}` AS `n`,`{$this->destructionTable}` AS `d`  
			WHERE d.`destruction_id` = n.`destruction_id` 
				AND n.`date_end` < SYSDATE()";
		$result = $this->query($query);
		
		//make invalid the news if they expired________________________________
		$query = "UPDATE `{$this->newsTable}` 
				SET `valid`=0  
				WHERE `date_end` < SYSDATE()";
		$result = $this->query($query);
		//remove the properties for which the news have exipired_______________
		$query = "SELECT * 
				FROM `{$this->newsTable}` 
				WHERE `valid`=0";
		$result = $this->query($query);
		if(count($result)>0){
			foreach($result as $res) {
				$marker_id = $res[$this->newsTable]['marker_id'];
				//GET the ids of the markers to delete_________________________
				$results_mark = $this->query("SELECT `marker_id` 
						FROM `{$this->useTable}` 
						WHERE `marker_id`={$marker_id} AND `valid`=0");
				foreach($results_mark as $resm){
					//delete from the user_properties the info_________________
					$this->query("DELETE FROM `{$this->userPropsTable}` 
							WHERE `marker_id`={$resm[$this->useTable]['marker_id']}");			
				}
				//delete the markers___________________________________________
				$this->query("DELETE FROM `{$this->useTable}` 
						WHERE `marker_id`={$marker_id} AND `valid`=0");
			}
		}	
	}
	
	function getMoneyUpdates() {
		$query = "SELECT SUM(m.`revenue`) AS `total_revenue`, p.`user_id`
				FROM `{$this->useTable}` AS `m`, `{$this->userPropsTable}` AS `p` 
				WHERE p.`marker_id` = m.`marker_id` AND 
				 	m.`valid` = 1 
				GROUP BY p.`user_id`";
		$result = $this->query($query);
		if(count($result)>0) {
			foreach($result as $res) {
				$info = array_merge($res[0],$res['p']);
				$this->query("UPDATE `{$this->usersInfoTable}` 
							SET `money`= `money`+{$info['total_revenue']} 
							WHERE `user_id` = {$info['user_id']}");	
			}	
		}
	}

	function regionsWorthUpdate(){
		$query = "SELECT `region_id`, `region_pop` 
				FROM `{$this->regionsTable}`";
		$result = $this->query($query);
				
		$queryAvg = "SELECT AVG(`region_pop`) as `avg_pop` 
				FROM `{$this->regionsTable}`";
		$resultAvg = $this->query($queryAvg);		
		$avgPop = 1;
		foreach($resultAvg as $resAvg){
			$avgPop = $resAvg[0]["avg_pop"];
		}

		foreach($result as $res){
				//get all buildings in that region_____________________________
				$result_build = $this->query("SELECT * 
					FROM `{$this->useTable}` 
					WHERE `region_id` = {$res[$this->regionsTable]['region_id']}");		
				$buildings = array();
				
				$result_nec = $this->query("SELECT `necessity_type`,`building_type`
					FROM `{$this->markerNecessTable}`");
				$primary = array();
				$secondary = array();
				$extra = array();		
				foreach($result_nec as $res_nec){
					if($res_nec[$this->markerNecessTable]['necessity_type']==1){
						$primary[] = $res_nec[$this->markerNecessTable]['building_type'];	
					}elseif($res_nec[$this->markerNecessTable]['necessity_type']==2){
						$secondary[] = $res_nec[$this->markerNecessTable]['building_type'];		
					}elseif($res_nec[$this->markerNecessTable]['necessity_type']==3){
						$tertiary[] = $res_nec[$this->markerNecessTable]['building_type'];	
					}elseif($res_nec[$this->markerNecessTable]['necessity_type']==4){
						$extra[] = $res_nec[$this->markerNecessTable]['building_type'];	
					}
				}			
						
				foreach($result_build as $resb) {
					$buildings[] = $resb[$this->useTable];
				}
				//do the region's worth update_________________________________
				$regPop  = $res[$this->regionsTable]['region_pop'];	
				$value4Region = $this->getValue4RegionWorth($buildings,$primary,$secondary,$tertiary,$extra,$regPop,$avgPop);
				$this->query("UPDATE `{$this->regionsTable}` 
					SET `region_worth`= {$value4Region} 
					WHERE `region_id` = {$res[$this->regionsTable]['region_id']}");
		}
	}
	
	function buildingValueUpdate(){
		$query = "SELECT m.`marker_id`,m.`building_condition`,m.`building_type`, 
						r.`region_worth`, r.`region_id`
				FROM `{$this->useTable}` AS `m`, `{$this->regionsTable}` as `r` 
				WHERE m.`region_id` = r.`region_id`";
		$result = $this->query($query);		
		foreach($result as $res){
				$info = array_merge($res['m'],$res['r']);
				$value4Building = $this->getValue4Building($info['building_condition'],
					$info['region_worth'], $info['building_type']);
				$value4Revenue = $this->getValue4Revenue($info['building_condition'],
					$info['region_worth'], $info['building_type'],$info['region_id']);
				$this->query("UPDATE `{$this->useTable}` 
					SET `value`= {$value4Building} 
					WHERE `marker_id` = {$info['marker_id']}");
				$this->query("UPDATE `{$this->useTable}` 
					SET `revenue` = {$value4Revenue} 
					WHERE `marker_id` = {$info['marker_id']}");
		}
	}
		
	function getRegions($game_id){
		$query = "SELECT r.* 
				FROM `{$this->regionsTable}` as r, {$this->gameTable} as g 
				WHERE g.`game_id` = r.`game_id` 
					AND g.`game_id` = {$game_id}";
		$result  = $this->query($query);		
		$regions = array();
		foreach($result as $res) {
			$regions[$res['r']['region_id']] = $res['r'];	
		}
		return $regions;
	}
	
	function getMaxRegionWorth($game_id){
		$query = "SELECT MAX(r.`region_worth`) as `max` 
				FROM `{$this->regionsTable}` as r, 
					`{$this->gameTable}` as g 
				WHERE r.`game_id` = g.`game_id` 
					AND g.`game_id` = {$game_id}
				GROUP BY g.`game_id`";
		$result  = $this->query($query);		
		$max = 0;
		foreach($result as $res) {
			$max = $res[0]['max'];	
		}
		return $max;
	}

	function setRegionPop($region_population){
		foreach($region_population as $region_id => $pop){
			$this->query("UPDATE `{$this->regionsTable}` 
				SET `region_pop` = {$pop} 
				WHERE `region_id` = {$region_id}");
		}
	}
	
	//TODO: value settings & stuff_____________________________________________
	function getValue4Update($building_cond,$old_cond) {
		$difference_cond = $building_cond-$old_cond;
		return (int)(pow($building_cond,2) * $this->update_price_constant * 
					$difference_cond);
	}

	function getValue4Revenue($building_cond, $region_worth, $building_type, $region_id) {
		//get the necessity type______________________________________________
		$result_necc = $this->query("SELECT `necessity_type` 
			FROM `{$this->markerNecessTable}` 
			WHERE `building_type` = '{$building_type}'");
		$necessity_type = 1;
		foreach($result_necc as $res){
			$necessity_type = $res[$this->markerNecessTable]['necessity_type'];
		}
		//get the sum of the values for this type of building in this region___
		$result_necc = $this->query("SELECT SUM(`building_condition`) as `cond` 
			FROM `{$this->markerTable}` 
			WHERE `building_type` = '{$building_type}' 
				AND `region_id` = {$region_id} 
			GROUP BY `region_id`");		
		$corresp_cond_sum = $building_cond;
		foreach($result_necc as $res){
			$corresp_cond_sum = $res[0]['cond'];
		}
		$value = (int)($region_worth*($necessity_type/$this->necessityUnits) * 
				($building_cond/$corresp_cond_sum) * $this->revenue_constant);
		/*
		echo "Val: ".$value."<br/>";
		echo "Reg Worth: ".$region_worth."<br/>";
		echo "Cond ".$building_cond."<br/>";
		echo "Corr_Cond ".$corresp_cond_sum."<br/>";
		*/
		return $value * $this->revenueConstant;
	}
		
	function getValue4Building($building_cond, $region_worth, $building_type) {
		$result_nec = $this->query("SELECT `necessity_type` 
			FROM `{$this->markerNecessTable}` 
			WHERE `building_type`='{$building_type}'");
		$necessity_type = 1;
		foreach($result_nec as $res) {
			$necessity_type = $res[$this->markerNecessTable]['necessity_type'];
		}	
		return (int)((pow($building_cond,2) * $region_worth)/$this->building_constant 
				*($necessity_type/$this->necessityUnits));
	} 
	
	function getUserRanking($user_id){
		//get the values of all his buildings_________________________________
		$total_building_value = 1;
		$result = $this->query("SELECT SUM(m.`value`) as `total`
			FROM `{$this->markerTable}` as `m`,
				`{$this->userPropsTable}` as `p` 
			WHERE p.`user_id` = {$user_id} 
				AND p.`marker_id` = m.`marker_id` 
			GROUP BY p.`user_id`");
		foreach($result as $res){
			$total_building_value = $res[0]['total'];
		}
		
		//get the money_______________________________________________________
		$money = 0;
		$result = $this->query("SELECT `money`
			FROM `{$this->usersInfoTable}`
			WHERE `user_id` = {$user_id}");
		foreach($result as $res){
			$money = $res[$this->usersInfoTable]['money'];
		}
		return floor(sqrt(0*$money + 1.0*$total_building_value));
		//return floor(sqrt($money + $total_building_value));
	}
		
	function getValue4RegionWorth($buildings,$primary,$secondary,$tertiary,$extra,$pop,$avgPop){
		//depends on building conditions & nr of buildings & building types
		//GET THE NECESSITIES FROM THE "buildings" ARRAY!!!!!!!!!!!!!!!!!
		
		$starter = 50;	// starter value: in case only 1 building is built in region, it should influence a bit 
		$empty   = 50;	// value for empty region
		$const   = 200; // balancing value for region (finding a good one is important!)
		
		// compute what necessities are present in the region ("buildings" 
		// array based on the "building_type")
		$p = $this->necessityFulfilled($buildings,$primary);
		$s = $this->necessityFulfilled($buildings,$secondary);
		$t = $this->necessityFulfilled($buildings,$tertiary);
		$e = $this->necessityFulfilled($buildings,$extra);
		$tot = $p + $s + $t +$e+1;
		// 4 variables representing perfect balance within region:
		$e1 = 0.4;
		$e2 = 0.1;
		$e3 = 0.2;
		$e4 = 0.3;
		// Calculate error within the perfect balance: 
		$err = 
			abs($e1 - $p/$tot)+
			abs($e2 - $s/$tot)+
			abs($e3- $t/$tot)+
			abs($e4 - $e/$tot);
		$res = (1-$err);
//		echo "Pop: ".$pop."<br/>";
//		echo "Avg pop: ".$avgPop."<br/>";
//		echo "Tot: ".$res."<br/>";
//		echo "values: ".$p." ".$s." ".$t." ".$e."<br/>";
//		echo "err: ".$err."<br/>";
/*	
		$isPrimary   = $this->necessityFulfilled($buildings,$primary);
		$isSecondary = $this->necessityFulfilled($buildings,$secondary);
		$isTertiary  = $this->necessityFulfilled($buildings,$tertiary);
		$isExtra     = $this->necessityFulfilled($buildings,$extra);
		if($isPrimary && !$isSecondary && !$isTertiary){
			$region_worth = 1000;
		}elseif(!$isPrimary && $isSecondary && !$isTertiary){
			$region_worth = 500;
		}elseif(!$isPrimary && !$isSecondary && $isTertiary){
			$region_worth = 200;
		}elseif($isPrimary && $isSecondary && !$isTertiary){
			$region_worth = 2000;
		}elseif(!$isPrimary && $isSecondary && $isTertiary){
			$region_worth = 800;
		}elseif($isPrimary && !$isSecondary && $isTertiary){
			$region_worth = 1400;
		}elseif($isPrimary && $isSecondary && $isTertiary){
			$region_worth = 4000;
		}else {
			$region_worth = 100;
		}
*/
		$buildingCondSum = 0;
		$buildingCntr    = 0;
		if(count($buildings)>0){
			foreach($buildings as $build){
				$buildingCondSum += (int)$build['building_condition'];
				$buildingCntr++;
			}
			$avgBuildCond = $buildingCondSum/$buildingCntr;
		}else {
			$avgBuildCond = $this->reasonableCond;
		}
		//$region_worth is updated with a factor that indicates how good the 
		//condition is of the buildings in that region.
		//$region_worth = $res*($avgBuildCond/$this->reasonableCond)*($pop/$avgPop);
		$region_worth = ($pop/$avgPop) * ($avgBuildCond/$this->reasonableCond) * $res * $const;
		//$region_worth = $region_worth*($avgBuildCond/$this->reasonableCond)*($pop/$avgPop);
		
		//echo "new: ".$res*($avgBuildCond/$this->reasonableCond)*($pop/$avgPop)."<br/>";
		//echo "old: ".$region_worth*($avgBuildCond/$this->reasonableCond)*($pop/$avgPop)."<br/>";
		if ((int)$region_worth > 0) {
			return $region_worth + $starter;	
		} else {
			return $empty;
		}
	}
	
	function necessityFulfilled($buildings,$necessity){
		//check if necessity is fullfilled...
		foreach($buildings as $build){
			$buildingType = $build['building_type'];
			if(in_array($buildingType,$necessity)){
				//if building type is element of this necessity
				$typeIdxInArray = array_search($buildingType,$necessity);
				//check as marked (replace name by one)
				$necessity[$typeIdxInArray] = 1;
			}
		}
		$necessityCount = 0;
		foreach($necessity as $i){
			//count number of buildings present for this necessity
			if($i==1){
				$necessityCount++;
			}
		}
		if($necessityCount==count($necessity)){
			//if all building types for this necessity are fullfilled return true
			return $necessityCount;
			//return True;
		}else{
			return $necessityCount;
			//return False;
		}
	}
	
	//DONE: NIMROD
	function initializeSwarm($game_id) {
		//var_dump($game_id);
	  	// Gaussian noise
	  	//the swarm has: 10x10 cells for each one of the 100 regions => 100x100 numbers in the final map
	  	//initialize all swarms for each game
		$swarm_file = fopen("js/swarm{$game_id}.js","w");
		if($swarm_file) {
			//initialize the swarm....
			fwrite($swarm_file, "var swarm=[\n");
			$maxPop = $this->avg_pop_at_init*2;
			for($row=0;$row<$this->swarm_rows;$row++){
				fwrite($swarm_file, "[");
				for($col=0;$col<$this->swarm_cols;$col++){
					$rand_nr = rand(0,$maxPop);
					fwrite($swarm_file, $rand_nr);
					if($col!=$this->swarm_cols-1){
						fwrite($swarm_file, ", ");
					}
				}
				if($row==$this->swarm_rows-1){
					fwrite($swarm_file, "]\n");
				}else{
					fwrite($swarm_file, "],\n");
				}
			}
			fwrite($swarm_file, "];\n");
			fwrite($swarm_file, "var epsilon = 1.0;\n");
			fclose($swarm_file);
		}

		$swarm = array();
		$swarm_file = fopen("js/swarm{$game_id}.js","r");
		if ($swarm_file) {
		    while (!feof($swarm_file)) {
		        $line = trim(fgets($swarm_file));
		        $lineVect = split(" ",$line);
		        if(!in_array("var",$lineVect) && count($lineVect)>3){
		     		$swarm[] = $lineVect;	   		
		        }elseif(in_array("epsilon",$lineVect)){
					$epsilon = (int)(str_replace(";","",$lineVect[count($lineVect)-1]));
				}
		    }
		    fclose($swarm_file);
		}

		// parse swarm and calculate the total population for 10x10 regions
		$region_pop_col = array();
		$region_pop_row = array();
		for($reg_row=0; $reg_row<10; $reg_row++){
			for($reg_col=0; $reg_col<10; $reg_col++){
				$region_pop = 0;
				for($row=0;$row<10;$row++){ 
					for($col=0;$col<10;$col++){
						$cell = (int)str_replace("]","",
									 str_replace(",","",
									 str_replace("[","",
									 	$swarm[$row*$reg_row][$col*$reg_col])));
						$region_pop += $cell;
					}
				}
				$region_pop_row[] = $region_pop;
			}
			$region_pop_col[] = $region_pop_row;
			$region_pop_row = array();
		}
		
		// get all regions from the current game
		$query = "SELECT DISTINCT r.`region_id`
				FROM `{$this->regionsTable}` AS `r`,
					  {$this->gameTable}     AS `g`
				WHERE r.`game_id`=g.`game_id`
				AND 	g.`game_id`={$game_id}";
		$result = $this->query($query);
		$regions = array();
		foreach($result as $res) {
			$regions[] = $res['r']['region_id'];
		}
		//var_dump($regions);

		// update the regions with the initial values for population
		$region_idx = 0;
		$totPop = 0;
		for($row=0;$row<count($region_pop_col);$row++){ 
			for($col=0;$col<count($region_pop_col[$row]);$col++){
				$this->query("UPDATE `{$this->regionsTable}` 
					SET `region_pop`= {$region_pop_col[$row][$col]}
					WHERE `region_id` = {$regions[$region_idx]}");
				//echo $regions[$region_idx]."\n";
				$totPop += $region_pop_col[$row][$col];
				$region_idx++;
				//var_dump($regions[0]['r']['region_id']);
			}
		}
		
		$query = "INSERT INTO `{$this->gameTimeTable}` (`game_time_id`, `game_id`, `game_time`, `game_time_max`)
				VALUES (NULL,{$game_id},0, 1000)";
		$result = $this->query($query);
		
		$queryPop = "UPDATE `{$this->gameTimeTable}`
					SET total_population = {$totPop}
					WHERE `game_id` = {$game_id}";
		$resultPop = $this->query($queryPop);
		
	}

	//DONE: SILVIA
	function getNeighbors($id,$scale){
		$id = (($id%100==0)?100:($id%100));		
		if($id == 1) {//top-left corner
			$neighbors = array(2+100*$scale,11+100*$scale,12+100*$scale);
		} elseif($id == 10) { //top-right corner
			$neighbors = array(9+100*$scale,19+100*$scale,20+100*$scale);
		} elseif($id == 91){ //bottom-left corner
			$neighbors = array(81+100*$scale,82+100*$scale,92+100*$scale);
		} elseif($id == 100) { //bottom-right corner
			$neighbors = array(89+100*$scale,99+100*$scale,90+100*$scale);
		} elseif((int)($id/10) == 0) { //first row
			$neighbors = array($id+1+100*$scale,$id-1+100*$scale,$id+10+100*$scale,
						$id+9+100*$scale,$id+11+100*$scale);
		} elseif($id % 10 == 1) { //first column
			$neighbors = array($id+1+100*$scale,$id-10+100*$scale,$id+10+100*$scale,
						$id-9+100*$scale,$id+11+100*$scale);	
		} elseif((int)($id/10) == 9) { //last row
			$neighbors = array($id+1+100*$scale,$id-1+100*$scale,$id-10+100*$scale,
						$id-9+100*$scale,$id-11+100*$scale);
		} elseif($id % 10 == 0) { //last column
			$neighbors = array($id-10+100*$scale,$id+10+100*$scale,$id-1+100*$scale,
						$id-11+100*$scale,$id+9+100*$scale);	
		} else { //center cells
			$neighbors = array($id-1+100*$scale,$id-10+100*$scale,$id+1+100*$scale,
						$id+10+100*$scale,$id+11+100*$scale,$id+9+100*$scale,
						$id-11+100*$scale,$id-9+100*$scale);
		}	
		/*1  2  3  4  5  6  7  8  9 10
		 11 12 13 14 15          19 20        
		 21 22 23                29 30		
		 ...
		 81 82 83                89 90
		 91 92 93                99 100 */
		return $neighbors;
	}
	
	function largerNeighbors($neighbors,$regions,$region_worth){
		$larger = 0;
		foreach($neighbors as $neigh) {
			if($regions[$neigh]['region_worth']>$region_worth) {
				$larger += 1;		
			}
		}
		return $larger;
	}
	
	function smallerNeighbors($neighbors,$regions,$region_worth){
		$smaller = 0;
		foreach($neighbors as $neigh) {
			if($regions[$neigh]['region_worth']<$region_worth) {
				$smaller += 1;		
			}
		}
		return $smaller;
	}
	
	function getBestNeighbor($neighbors,$regions,$region_worth,$id) {
		$best = $id;
		$max  = $region_worth;
		foreach($neighbors as $neigh){
			if($regions[$neigh]['region_worth']>$max) {
				$max = $regions[$neigh]['region_worth'];
				$best = $neigh;
			}
		}
		return $best;
	}
	
	function updateSwarm($game_id) {
		$games = $this->getGameIds();
		//var_dump($games);
		//get all regions____________________________________________________	
		$regions  = $this->getRegions($game_id);			
		$maxworth = $this->getMaxRegionWorth($game_id);	
		//loop over all regions_______________________________________________
		$scaled   = 0;
		foreach($regions as $id=>$reg) {
			if($scaled == 0){
				$scaled = ($reg['region_id']%100==0?(int)($reg['region_id']/100)-1:
					(int)($reg['region_id']/100)); 
			}		
			$region_population = 0;
			$neighbors      = $this->getNeighbors($reg['region_id'],$scaled);				 
			$counts_larger  = $this->largerNeighbors($neighbors,$regions,$reg['region_worth']);
			$counts_smaller = $this->smallerNeighbors($neighbors,$regions,$reg['region_worth']);
			if($counts_smaller>$counts_larger && $counts_smaller>=(int)(count($neighbors)/2)) {
				//swarm people die
				$regions[$id]['extra_pop'] = -1 * rand(1,$this->bornPopSwarm);		
			}elseif($counts_larger>$counts_smaller && $counts_larger>=(int)(count($neighbors)/2)){
				//swarm people are born
				$regions[$id]['extra_pop'] = rand(1,$this->bornPopSwarm);		
			}else{
				$regions[$id]['extra_pop'] = 0;
			}
			$regions[$id]['best_neighbor'] = $this->getBestNeighbor($neighbors,$regions,$reg['region_worth'],$id);	
			$regions[$id]['worth_diff'] = abs($regions[$regions[$id]['best_neighbor']]['region_worth']-$reg['region_worth']);
		}
		
		//read the old swarm from the file_____________________________________
		$swarm = array();
		$swarm_file = fopen("js/swarm{$game_id}.js","r");
		if ($swarm_file) {
		    while (!feof($swarm_file)) {
		        $line = trim(fgets($swarm_file));
		        $lineVect = split(" ",$line);
		        $lineVect = str_replace(",","",$lineVect);
				$lineVect = str_replace("[","",$lineVect);
    			$lineVect = str_replace("]","",$lineVect);
		        
		        if(!in_array("var",$lineVect) && count($lineVect)>3){
		     		$swarm[] = $lineVect;	   		
		        }elseif(in_array("epsilon",$lineVect)){
		        	$epsilon = (float)(str_replace(";","",$lineVect[count($lineVect)-1]));
		        }
		    }
		    fclose($swarm_file);
		}
		//update the epsilon for the probability______________________________
		
		if($epsilon>$this->minimum_epsilon){
				$epsilon -= 0.005;
		}
		//update the swarm_____________________________________________________
		for($row=0;$row<count($swarm);$row++){ 
			for($col=0;$col<count($swarm[$row]);$col++){
				//with a probability dependent on (the difference between worths + epsilon learning rate :P)
				$curr_region = ($this->swarm_cell_rows)*(int)($row/$this->swarm_cell_rows) 
								+ (int)($col/$this->swarm_cell_cols)+1;
				$curr_region = $curr_region+(100*$scaled);
				
				//compute the corrsponding region in the swarm array
				$best_neigh = $regions[$curr_region]['best_neighbor'];		
				$best_neigh = (($best_neigh%100==0)?100:($best_neigh%100));		
				
				if($best_neigh%$this->swarm_cell_cols == 0){
					$best_col = $this->swarm_cell_cols*$this->swarm_cell_rows; 
					$best_row = (int)($best_neigh/$this->swarm_cell_rows)*
								$this->swarm_cell_rows; 
				} else {
					$best_col = (int)($best_neigh%$this->swarm_cell_cols)*$this->swarm_cell_cols; 
					$best_row = (int)(($best_neigh/$this->swarm_cell_rows)+1)*
								$this->swarm_cell_rows; 	
				}					
				$extra_pop	= $regions[$curr_region]['extra_pop'];
				$worth_diff = $regions[$curr_region]['worth_diff'];

				//TODO: this updates makes too much change.
				//when region gets negative extra_pop all its cells loose population
				if($swarm[$row][$col]+$extra_pop>$this->minimum_pop){
					$swarm[$row][$col] = $swarm[$row][$col] + $extra_pop * $this->birth_rate;
				}
				//compute the moving rate_____________________________________
				if($swarm[$row][$col]>$this->minSwarmPop){
					$moving_population = (int)(($swarm[$row][$col]-$this->minSwarmPop)*($worth_diff/$maxworth));
				}else{
					$moving_population = 0;
				}
				if($swarm[$row][$col]>$moving_population && $moving_population>0){
					//move with a probability invers proportional with epsilon: 
					//epsilon decreases => probability increases	
					$rand = rand(0,1000);
					if($rand>$epsilon*1000) {
						$rand_col = rand($best_col-$this->swarm_cell_cols,$best_col-1);
						$rand_row = rand($best_row-$this->swarm_cell_rows,$best_row-1);
						
						//TODO: check if extra checks are needed to avoid wrong population movement
						$toCell   = $swarm[$rand_row][$rand_col] + $moving_population;
						$fromCell = $swarm[$row][$col] - $moving_population;		
						if($fromCell >= $this->minSwarmPop && 
							$toCell <= $this->maxSwarmPop ){

							$swarm[$row][$col] = $swarm[$row][$col] - $moving_population;
							$swarm[$rand_row][$rand_col] = $swarm[$rand_row][$rand_col] + $moving_population;
						}
					}
				}

				//Randome move between neighboring regions________________________
				$neighbors      = $this->getNeighbors($curr_region,$scaled);
				//randomely select a neighbor that will get the random moving swarm people
				$receivingNeighbor = $neighbors[rand(0,count($neighbors)-1)];
				$receivingNeighbor = (($receivingNeighbor%100==0)?100:($receivingNeighbor%100));
				//calculate the max column and row of the receiving region
				if($receivingNeighbor%$this->swarm_cell_cols == 0){
					$receiving_col = $this->swarm_cell_cols*$this->swarm_cell_rows; 
					$receiving_row = (int)($receivingNeighbor/$this->swarm_cell_rows)*
								$this->swarm_cell_rows; 
				} else {
					$receiving_col = (int)($receivingNeighbor%$this->swarm_cell_cols)*$this->swarm_cell_cols; 
					$receiving_row = (int)(($receivingNeighbor/$this->swarm_cell_rows)+1)*
								$this->swarm_cell_rows; 	
				}					
				//randomely select a cell in the receiving neighbor that will get the moving population
				$receiving_col = $receiving_col - rand(1,10);
				$receiving_row = $receiving_row - rand(1,10);

				$rndMovePercentage = rand(1,$this->PercentageRndMove);
				$popToMove = (int)(($swarm[$row][$col]-$this->minSwarmPop)*($rndMovePercentage/100));
				
//				echo $receiving_row."<br/>";
//				echo $receiving_col."<br/>";
				$toCell   = $swarm[$receiving_row][$receiving_col] + $popToMove;
				$fromCell = $swarm[$row][$col] - $popToMove;		
				if($fromCell >= $this->minSwarmPop && 
					$toCell <= $this->maxSwarmPop ){
					$swarm[$receiving_row][$receiving_col] = $toCell;
					$swarm[$row][$col] = $fromCell;
				}
			}
		}

		$region_population = array();
		
		//write it to the file_____________________________________________________
		$swarm_file = fopen("js/swarm{$game_id}.js","w");
		
		$totPop = 0;
		if ($swarm_file) {
			fwrite($swarm_file, "var swarm = [\n");
			for($row=0;$row<count($swarm);$row++){
				fwrite($swarm_file,"[");	
				for($col=0;$col<count($swarm[$row]);$col++){
					//get region_id________________________________________
					$curr_region_id = ($this->swarm_cell_rows)*(int)($row/$this->swarm_cell_rows) + 
							(int)($col/$this->swarm_cell_cols)+1;
					$curr_region = $curr_region+100*$scaled;
							
					if(!array_key_exists($curr_region_id, $region_population)){
						$region_population[$curr_region_id] = 0;
					}
			
					$region_population[$curr_region_id] += $swarm[$row][$col];				
					fwrite($swarm_file, $swarm[$row][$col]);
					$totPop += $swarm[$row][$col]; 
		     		if($col!=count($swarm[$row])-1){
		      			fwrite($swarm_file, ", ");
		     		}
		    	}
		    	if($row==count($swarm)-1){
		     		fwrite($swarm_file, "]\n");
		    	}else{
		     		fwrite($swarm_file, "],\n");
		    	}   
			}
			fwrite($swarm_file, "];\n");
			fwrite($swarm_file, "var epsilon = {$epsilon};\n");   
			fclose($swarm_file);
		}
		//update the region's worth wrt to the population______________________
		$this->setRegionPop($region_population);

		
		$queryPop = "UPDATE `{$this->gameTimeTable}`
					SET total_population = {$totPop}
					WHERE `game_id` = {$game_id}";
		$resultPop = $this->query($queryPop);
	}
	
	
	function updateSwarms() {
		//calls the regionsWorthUpdate, moneyUpdate, buildingValueUpdate, updateSwarm
		//$this->Cron->updateSwarm($game_id);	
		$query = "SELECT t.`game_id` FROM `{$this->gameTimeTable}` as `t`";
		$result = $this->query($query);
		foreach ($result as $res) {
			$game_id = $res['t']['game_id'];
			echo $game_id."<br/>";
			$this->updateSwarm($game_id);
			$query2 = "UPDATE `{$this->gameTimeTable}` 
				SET game_time = game_time + 1
				WHERE `game_id` = {$game_id}";
			$update = $this->query($query2);

			$query3 = "SELECT t.`game_time`, t.`game_time_max` 
					FROM `{$this->gameTimeTable}` AS `t`
					WHERE t.`game_id` = {$game_id} 
						AND t.`game_time` >= t.`game_time_max`";
			$time = $this->query($query3);
			if(count($time) > 0) {
				echo "STOP GAME<br/>";
				$this->createRankList($game_id);
				$this->deleteGame($game_id);
			} else {
				echo "CONTINUE GAME<br/>";
			}
		}
	}
	
	function orderProfilesByNetworth($a, $b) {
		// order net worth of players descending
		if (isset($a['net_worth']) && isset($b['net_worth'])) {
			if ($a['net_worth'] > $b['net_worth']) {return -1;}
			if ($a['net_worth'] < $b['net_worth']) {return 1;}
		}
		return 0;
	}
	
	function createRankList($game_id) {
		$query1 = "SELECT u.`user_id`, u.`first_name`,u.`last_name`,u.`money`				
				FROM `{$this->usersInfoTable}` AS `u`, `{$this->gameTable}` as `g` 
				WHERE g.`user_id` = u.`user_id` AND g.`game_id` = {$game_id}";
		$result = $this->query($query1);
		$user_info = array();

		$statistics = array();
		$getcityname = "SELECT DISTINCT l.`city_name`
					FROM `{$this->gameLocatonsTable}` AS `l`,
					{$this->gameTable} AS `g`
					WHERE l.`game_location_id` = g.`game_location_id`
					AND g.`game_id` = {$game_id}";
		$citynameres = $this->query($getcityname);
		$statistics['city_name'] = $citynameres[0]['l']['city_name']; 
		$getgamename = "SELECT DISTINCT g.`game_name`
					FROM {$this->gameTable} AS `g`
					WHERE g.`game_id` = {$game_id}";
		$gamenameres = $this->query($getgamename);
		$statistics['game_name'] = $gamenameres[0]['g']['game_name']; 
		foreach ($result as $res) {
			//get nr of properties_______________________________________
			$query2 = "SELECT COUNT(p.`property_id`) AS `no_props`				
				FROM `{$this->userPropsTable}` AS `p`,
						`{$this->markerTable}` AS `m`
				WHERE p.`user_id` = {$res['u']['user_id']} AND 
					p.`marker_id` = m.`marker_id` AND
					m.`valid` = 1
				GROUP BY p.`user_id`";
			$result2 = $this->query($query2);
			$temp = array();
			foreach($result2 as $res2) {
				$temp['no_props'] = $res2[0]['no_props'];
			}
			//get no of received attacks__________________________________			
			$query3 = "SELECT COUNT(a.`news_id`) AS `no_received_attacks`
					FROM `{$this->newsTable}` AS `a`				 
					WHERE a.`marker_id` IN (SELECT m.`marker_id` 
									FROM `{$this->markerTable}` AS `m`,
									 	`{$this->userPropsTable}` AS `p`
									WHERE m.`marker_id`= p.`marker_id` 
										AND p.`user_id` = {$res['u']['user_id']})";
			$result3 = $this->query($query3);
			foreach($result3 as $res3) {
				$temp['no_received_attacks'] = $res3[0]['no_received_attacks'];
			}
			//get no of sent attacks__________________________________________
			$query4 = "SELECT COUNT(n.`news_id`) AS `no_sent_attacks`				
					FROM `{$this->newsTable}` AS `n`			 
					WHERE n.`author_id` = {$res['u']['user_id']}";
			$result4 = $this->query($query4);
			foreach($result4 as $res4) {
				$temp['no_sent_attacks'] = $res4[0]['no_sent_attacks'];
			}
			//get favorite attacks____________________________________________
			$query5 = "SELECT d.`destruction_name`, 
				COUNT( n.`destruction_id` ) AS `nr` 
				FROM `{$this->destructionTable}` AS d, `{$this->newsTable}` AS n
				WHERE d.`destruction_id` = n.`destruction_id`
					AND n.`author_id` = {$res['u']['user_id']}
				GROUP BY n.`destruction_id`
				ORDER BY nr DESC
				LIMIT 0 , 1";
			$result5 = $this->query($query5);
			foreach($result5 as $res5) {
				$temp['fav_attack'] = $res5['d']['destruction_name'];
			}
			//get favorite building___________________________________________
			$query6 = "SELECT m.`building_type`,
				COUNT( m.`building_type` ) AS `nr` 
				FROM `{$this->userPropsTable}` AS p, `{$this->markerTable}` AS m
				WHERE p.`user_id` = {$res['u']['user_id']} AND
					p.`marker_id`= m.`marker_id` AND
					m.`valid` = 1
				GROUP BY m.`building_type`
				ORDER BY nr DESC
				LIMIT 0 , 1";
			$result6 = $this->query($query6);
			foreach($result6 as $res6) {
				$temp['fav_building'] = $res6['m']['building_type'];
			}
			// calculate net worth___________________________________________
			$query7 = "SELECT SUM(m.`revenue`) AS `total_revenue`		
				FROM `{$this->markerTable}` AS `m`,
					`{$this->userPropsTable}` AS `p`			 
				WHERE m.`marker_id` = p.`marker_id` AND
					p.`user_id`={$res['u']['user_id']} AND
					m.`valid` = 1
				GROUP BY p.`user_id`";
			$result7 = $this->query($query7);
			foreach($result7 as $res7) {
				$temp['total_revenue'] = $res7[0]['total_revenue'];
			}
			
			$temp['net_worth'] = $this->getUserRanking($res['u']['user_id']);
			// append temp to userarray______________________________________
			$user_info[$res['u']['user_id']] = array_merge($res['u'], $temp);
			
		}
		
		usort($user_info, array('Cron','orderProfilesByNetworth'));
		
		$ranking = fopen("../views/login/show_rankings.thtml","a+");
		if ($ranking) {
			fseek($ranking, SEEK_SET);
			$pos = 1;
			fwrite($ranking,"<div id=\"game\">\n");
			fwrite($ranking,"\tGame: ".$statistics['game_name']."<br/>\n");
			fwrite($ranking,"\tCity: ".$statistics['city_name']."<br/>\n");
			foreach ($user_info as $ui) {
				echo "Name: ".$ui['first_name']." ".$ui['last_name']."<br/>\n";
				fwrite($ranking,"\t<div id=\"player\">\n");
				fwrite($ranking, "\t\t[Pos: ".$pos."] ");
				fwrite($ranking, "[Net Worth: ".$ui['net_worth']."] ");
				$props = 0;
				if (isset($ui['no_props'])) { $props = $ui['no_props']; }
				fwrite($ranking, "[Properties: ".$props."] ");
				fwrite($ranking, "[Money: ".$ui['money']."] ");
				fwrite($ranking, "[Name: ".$ui['first_name']." ".$ui['last_name']."] ");
				fwrite($ranking,"\t</div>\n");
				$pos = $pos+1;
			}
			fwrite($ranking,"</div>\n");
			fclose($ranking);
		}
	}
	
	function deleteGame($game_id) {
		$query = "SELECT g.`game_id`, g.`user_id` 
			FROM `{$this->gameTable}` AS `g` 
			WHERE g.`game_id` = {$game_id}";
		$result = $this->query($query);
		//var_dump($result);
		
		$del_game = "DELETE g.* 
					FROM `{$this->gameTable}` AS `g`
					WHERE g.`game_id` = $game_id";
		$del_res = $this->query($del_game);

		$del_time = "DELETE t.* 
					FROM `{$this->gameTimeTable}` AS `t`
					WHERE t.`game_id` = $game_id";
		$del_res = $this->query($del_time);

		foreach ($result as $res) {
			//### CLEAR CHAT TABLE
			$del_chat = "DELETE c.*
						FROM `{$this->chatTable}` AS `c`
						WHERE c.`user_id`={$res['g']['user_id']}";
			$del_res = $this->query($del_chat);
			
			//### CLEAR MARKERS
			$del_markers = "DELETE m.* 
							FROM `{$this->markerTable}` AS `m`,
							`{$this->userPropsTable}` AS `p` 
							WHERE m.`marker_id`=p.`marker_id` AND
							p.`user_id` = {$res['g']['user_id']}";
			$del_res = $this->query($del_markers);

			//### CLEAR CLEAR USER PROPERTIES
			$del_prop = "DELETE p.*
						FROM `{$this->userPropsTable}` AS `p`
						WHERE p.`user_id` = {$res['g']['user_id']}";
			$del_res = $this->query($del_prop);
			
			//### CLEAR NEWS
			$del_news = "DELETE n.*
						FROM `{$this->newsTable}` AS `n`
						WHERE n.`author_id` = {$res['g']['user_id']}";
			$del_res = $this->query($del_news);
			
			//### CLEAR REGIONS
			$del_regions = "DELETE r.*
						FROM `{$this->regionsTable}` AS `r`
						WHERE r.`game_id` = {$game_id}";
			$del_res = $this->query($del_regions);

			//### CLEAR USERS
			$del_users = "DELETE u.*
						FROM `{$this->usersTable}` AS `u`
						WHERE u.`user_id` = {$res['g']['user_id']}";
			$del_res = $this->query($del_users);
			
			//### CLEAR USER INFORMATION
			$del_userinfo = "DELETE u.*
						FROM `{$this->usersInfoTable}` AS `u`
						WHERE u.`user_id` = {$res['g']['user_id']}";
			$del_res = $this->query($del_userinfo);
		}
		
		//### DELETE SWARM FILE
		unlink("js/swarm{$game_id}.js");
	}

}
